<?php
/** 
 * 
 *
 * @package api
 * @subpackage lang
 * @author Richard Fullmer <php-api@byu.edu>
 * @version 1.0
 */
/**
 *
 */
require_once( "lang/Object.php" );
require_once( "lang/Comparable.php" );
require_once( "lang/IllegalArgumentException.php" );
require_once( "lang/IndexOutOfBoundsException.php" );

/**
 * Class String
 *
 * The String class represents character strings. It acts as a wrapper for the PHP string literal.  If you wish to use store 
 * strings in any type of collection, you must use this class to wrap them.
 * 
 * Strings are constant; their values cannot be changed after they are created. String buffers support mutable strings. Because 
 * String objects are immutable they can be shared. For example:
 *          
 * The class String includes methods for examining individual characters of the sequence, for comparing strings, for 
 * searching strings, for extracting substrings, and for creating a copy of a string with all characters translated to 
 * uppercase or to lowercase. 
 *  
 * The PHP language provides special support for the string concatenation operator ( . ), and for conversion of other 
 * objects to strings. String concatenation is implemented through the StringBuilder(or StringBuffer) class and its append 
 * method. String conversions are implemented through the method toString, defined by Object and inherited by all classes 
 * in Java. 
 * 
 * Unless otherwise noted, passing a null argument to a constructor or method in this class will cause a NullPointerException 
 * to be thrown.
 *
 * @package api
 * @subpackage lang
 */
class String extends Object implements Comparable {

	// ================================ Private Members ==============================================
	
	private $value;
	private $hash = 0;
	
	// ================================ Public Methods ================================================
	
	public function __construct( $value ) {
		if (! is_string( $value ))
			throw new IllegalArgumentException();
		if ( is_null( $value ))
			throw new NullPointerException();	
			
		$this->value = $value;
		$this->size = strlen( $value );
	}
	
	public function charAt( $index ) {
		if ($index >= $this->size )
			throw new IndexOutOfBoundsException( "index is out of bounds" );
		return $this->value[$index]; 
	}
	
	public function compareTo( Object $o ) {
		if ( !$o instanceof String )
			throw new ClassCastException();
		return strcmp( $this->toString(), $o->toString() );
	}
	
	public function compareToIgnoreCase( String $str ) {
		if ( !$o instanceof String )
			throw new ClassCastException();
		return strcasecmp( $this->toString(), $o->toString() );
	}
	
	public function concat( String $str ) {
		return $this->value = $this->value + $str->toString();
	}
	
	public function contains( $s ) {
		if (strpos($this->value, $str))
			return true;
		return false;
	}
	
	public function contentEquals( $cs ) {
		return $this->value == $cs;
	}
	
	public function endsWith( $suffix ) {
		
	}
	
	public function equals( Object $o ) {
		if ( !$o instanceof String)
			return false;
		return ( $this->value == $o->toString());
	}
	
	public function equalsIgnoreCase( $str ) {
		if ( !$o instanceof String)
			return false;
		return ( $this->toLower()->toString() == $o->toLower()->toString());
	}
	
	public function hashCode() {
		$h = $this->hash;
		if ($h == 0) {
			for ($i = 0; $i < strlen( $this->value ); $i++) {
				$h = (int) (31 * $h + ord($this->value[$i]));
			}
			$this->hash = $h;
		}
		return $h;
	}
	
	public function length() {
		return strlen( $this->value );
	}
	
	public function matches( $regex ) {
		if (ereg( $regex, $this->value ))
			return true;
		return false;
	}
	
	public function replace( $target, $replacement ) {
		$this->value = str_replace( $target, $replacement, $this->value);
	}
		
	public function startsWith( $prefix ) {
	
	}
	
	public function substring( $beginIndex, $length = -1 ) {
		if ($length == -1)
			return substr($this->value, $beginIndex);
		else
			return substr( $this->value, $beginIndex, $length );
	}
	
	public function toLowerCase() {
		return strtolower( $this->value );
	}
	
	public function toUpperCase() {
		return strtoupper( $this->value );
	}
	
	public function trim() {
		return trim( $this->value );
	}
	
	public function toString() {
		return $this->value;
	}
	
	// =========================================== Static Methods ===================================================
	
	static public function booleanValueOf( $b ) {
		return (bool) $b;
	}
	static public function doubleValueOf( $c ) {
		return (float) $c;
	}
	static public function floatValueOf( $f ) {
		return (float) $f;
	}
	static public function intValueOf( $i ) {
		return (int) $i;
	}
}


?>